package com.ck.ips.service.impl;

import com.ck.common.model.*;
import com.ck.core.constant.BusinessConstant;
import com.ck.core.constant.ModuleConstant;
import com.ck.core.constant.SysConfigNameEnum;
import com.ck.core.constant.device.DeviceSettingType;
import com.ck.core.context.UserContextHolder;
import com.ck.core.util.FileUtils;
import com.ck.core.util.HuaWeiCloudUtils;
import com.ck.ips.dao.DeviceSettingMapper;
import com.ck.ips.dao.DeviceUpgradeMapper;
import com.ck.ips.model.vo.DeviceUpgradeInfoVO;
import com.ck.ips.service.DeviceService;
import com.ck.ips.service.DeviceUpgradeService;
import com.ck.ips.service.sys.OperationLogService;
import com.ck.ips.service.sys.SysConfigService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.dongliu.apk.parser.ApkFile;
import net.dongliu.apk.parser.bean.ApkMeta;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description: apk service
 * @author: zhanglei
 * @date: 2019/5/14 13:48
 */
@Service(value="deviceUpgradeService")
public class DeviceUpgradeServiceImpl implements DeviceUpgradeService {
    private Logger logger = LoggerFactory.getLogger(DeviceUpgradeServiceImpl.class);
    @Autowired
    DeviceUpgradeMapper deviceUpgradeMapper;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private DeviceSettingMapper deviceSettingMapper;
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private DeviceService deviceService;

    @Override
    public OperationResult<Object> getApkList(String versionName, String upgradeName, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<DeviceUpgrade> deviceUpgradeList = deviceUpgradeMapper.getApkList(versionName,upgradeName);
        PageInfo<DeviceUpgrade> pageInfo = new PageInfo<>(deviceUpgradeList);
        return OperationResult.newSuccessOperationResult(pageInfo);
    }

    @Override
    public OperationResult<Object> uploadApk(MultipartFile files) throws IOException {
        //文件上传地址
        String cloudFileDir = "ck/firmware/";
        if (files == null) {
            return OperationResult.newValidateFailOperationResult("上传文件不能为空");
        }else if(files.getSize() <= 0){
            return OperationResult.newValidateFailOperationResult("文件内容不能为空");
        }
        String originalFilename = files.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename)) {
            return OperationResult.newValidateFailOperationResult("文件名不能为空");
        }
        //文档文件后缀
        String extension = FilenameUtils.getExtension(originalFilename);
        //获取允许上传的apk格式
        String defaultSuffix = BusinessConstant.APK_TYPE;
        if (!extension.equals(defaultSuffix)) {
            return OperationResult.newValidateFailOperationResult("文件格式不对");
        }
        //文件上传
        String fileSaveURL = HuaWeiCloudUtils.uploadFile2HuaweiCloud(files,cloudFileDir);
        if (StringUtils.isBlank(fileSaveURL)) {
            return OperationResult.newValidateFailOperationResult("上传文件到华为云失败");
        }
        //返回信息Map
        List<Map<String,Object>> msgList = Lists.newArrayList();
        Map<String, Object> msgMap = Maps.newHashMap();

        //将MultipartFile转为File
        File apkFile = FileUtils.multipartFileConvertFile(files);
        //获取apk信息,自动关闭流
        try (ApkFile apk = new ApkFile(apkFile)) {
            ApkMeta apkMeta = apk.getApkMeta();
            String apkFileMD5 = FileUtils.getFileMD5(apkFile);
            msgMap.put("md5", apkFileMD5);
            msgMap.put("upgradeName", apkMeta.getName());
            msgMap.put("versionCode", apkMeta.getVersionCode());
            msgMap.put("packageName",apkMeta.getPackageName());
            msgMap.put("versionName", apkMeta.getVersionName());
            double size = files.getSize() / 1024.00 / 1024;
            DecimalFormat decimalFormat  =   new  DecimalFormat("##0.00");
            msgMap.put("size", decimalFormat.format(size));
        }
        //删除因MultipartFile转化为File后，创建的本地File文件
        if (apkFile.exists()) {
            if(!apkFile.delete()){
                logger.warn("uploadApk 删除无用图片文件失败");
            }
        }
        //检测apk版本是否已经在数据库中存在
        int count = deviceUpgradeMapper.getCountByVersionCode(String.valueOf(msgMap.get("versionName")),String.valueOf(msgMap.get("versionCode")));
        if(count>0){
            return OperationResult.newValidateFailOperationResult("APK已存在，请重新上传");
        }
        msgMap.put("url", buildPathName(fileSaveURL));
        msgList.add(msgMap);
        return OperationResult.newSuccessOperationResult(msgList);
    }

    @Override
    public OperationResult<Object> addApk(String upgradeName, Integer versionCode, String versionName, String packageName, String md5, String size, String url, Integer active, Integer isTiming, Long timingTime, String description) {
        if(StringUtils.isBlank(upgradeName)){
           return OperationResult.newValidateFailOperationResult("APK名称不能为空");
        }
        if(versionCode==null){
           return OperationResult.newValidateFailOperationResult("apk版本号不能为空");
        }
        if(StringUtils.isBlank(versionName)){
            return OperationResult.newValidateFailOperationResult("APK版本名称不能为空");
        }
        if(StringUtils.isBlank(packageName)){
            return OperationResult.newValidateFailOperationResult("APK包名称不能为空");
        }
        if(StringUtils.isBlank(md5)){
            return OperationResult.newValidateFailOperationResult("apk的MD5值不能为空");
        }
        if(StringUtils.isBlank(size)){
            return OperationResult.newValidateFailOperationResult("apk大小不能为空");
        }
        if(StringUtils.isBlank(url)){
            return OperationResult.newValidateFailOperationResult("apk下载地址不能为空");
        }
        if(active==null){
            active = BusinessConstant.DEVICE_UPGRADE_FORCE_NO;
        }
        if(isTiming==null){
            isTiming = BusinessConstant.DEVICE_UPGRADE_TIMING_NO;
        }else if(timingTime==null && isTiming==1){
            return OperationResult.newValidateFailOperationResult("定时升级时间不能为空");
        }
        String userName = UserContextHolder.currentUser().getUserName();
        Long nowTime = System.currentTimeMillis();
        DeviceUpgrade deviceUpgrade = new DeviceUpgrade();
        deviceUpgrade.setUploader(userName);
        deviceUpgrade.setAddTime(nowTime);
        deviceUpgrade.setUpgradeName(upgradeName);
        deviceUpgrade.setVersionCode(versionCode);
        deviceUpgrade.setVersionName(versionName);
        deviceUpgrade.setPackageName(packageName);
        deviceUpgrade.setUpgradeType(BusinessConstant.DEVICE_UPGRADE_TYPE_SOFTWARE);
        deviceUpgrade.setMd5(md5);
        deviceUpgrade.setSize(size);
        deviceUpgrade.setUrl(url);
        deviceUpgrade.setActive(active);
        deviceUpgrade.setIsTiming(isTiming);
        deviceUpgrade.setTimingTime(timingTime);
        deviceUpgrade.setDescription(description);
        deviceUpgrade.setStatus(BusinessConstant.APK_USE);
        deviceUpgradeMapper.addApk(deviceUpgrade);
        String msg = String.format("上传apk成功，版本名称[%s],版本号[%s]", versionName, versionCode);
        return OperationResult.newSuccessTipsOperationResult(msg);
    }

    @Override
    public OperationResult<Object> getApkById(Long deviceUpgradeId) {
        if(deviceUpgradeId==null){
            return OperationResult.newValidateFailOperationResult("deviceUpgradeId参数不能为空");
        }
        DeviceUpgrade deviceUpgrade = deviceUpgradeMapper.getApkById(deviceUpgradeId);
        return OperationResult.newSuccessOperationResult(deviceUpgrade);
    }

    @Override
    public OperationResult<Object> editApk(Long deviceUpgradeId, String upgradeName, Integer versionCode, String versionName, String packageName, String md5, String size, String url, Integer active, Integer isTiming, Long timingTime, String description) {
        if(deviceUpgradeId==null){
            return OperationResult.newValidateFailOperationResult("原APK的id不能为空");
        }
        if(StringUtils.isBlank(upgradeName)){
            return OperationResult.newValidateFailOperationResult("APK名称不能为空");
        }
        if(versionCode==null){
            return OperationResult.newValidateFailOperationResult("apk版本号不能为空");
        }
        if(StringUtils.isBlank(versionName)){
            return OperationResult.newValidateFailOperationResult("APK版本名称不能为空");
        }
        if(StringUtils.isBlank(packageName)){
            return OperationResult.newValidateFailOperationResult("APK包名称不能为空");
        }
        if(StringUtils.isBlank(md5)){
            return OperationResult.newValidateFailOperationResult("apk的MD5值不能为空");
        }
        if(StringUtils.isBlank(size)){
            return OperationResult.newValidateFailOperationResult("apk大小不能为空");
        }
        if(StringUtils.isBlank(url)){
            return OperationResult.newValidateFailOperationResult("apk下载地址不能为空");
        }
        if(active==null){
            active = BusinessConstant.DEVICE_UPGRADE_FORCE_NO;
        }
        if(isTiming==null){
            isTiming = BusinessConstant.DEVICE_UPGRADE_TIMING_NO;
        }else if(timingTime==null && isTiming==1){
            return OperationResult.newValidateFailOperationResult("定时升级时间不能为空");
        }
        Long nowTime = System.currentTimeMillis();
        DeviceUpgrade deviceUpgrade = new DeviceUpgrade();
        deviceUpgrade.setDeviceUpgradeId(deviceUpgradeId);
        deviceUpgrade.setUpdateTime(nowTime);
        deviceUpgrade.setUpgradeName(upgradeName);
        deviceUpgrade.setVersionCode(versionCode);
        deviceUpgrade.setVersionName(versionName);
        deviceUpgrade.setPackageName(packageName);
        deviceUpgrade.setUpgradeType(BusinessConstant.DEVICE_UPGRADE_TYPE_SOFTWARE);
        deviceUpgrade.setMd5(md5);
        deviceUpgrade.setSize(size);
        deviceUpgrade.setUrl(url);
        deviceUpgrade.setActive(active);
        deviceUpgrade.setIsTiming(isTiming);
        deviceUpgrade.setTimingTime(timingTime);
        deviceUpgrade.setDescription(description);
        deviceUpgradeMapper.editApk(deviceUpgrade);
        String msg = String.format("上传apk成功，版本名称[%s],版本号[%s]", versionName, versionCode);
        return OperationResult.newSuccessTipsOperationResult(msg);
    }

    @Override
    public OperationResult<Object> deleteApk(Long deviceUpgradeId) {
        if(deviceUpgradeId==null){
            return OperationResult.newValidateFailOperationResult("deviceUpgradeId参数不能为空");
        }
        DeviceUpgrade deviceUpgrade = deviceUpgradeMapper.getApkById(deviceUpgradeId);
        deviceUpgradeMapper.deleteApk(deviceUpgradeId);
        String msg = String.format("删除apk成功，版本名称[%s],版本号[%s]", deviceUpgrade.getVersionName(), deviceUpgrade.getVersionCode());
        return OperationResult.newSuccessTipsOperationResult(msg);
    }

    @Override
    public OperationResult<Object> upgradeApkToMips(String deviceCodes, Long deviceUpgradeId, String ip) {
        if(StringUtils.isBlank(deviceCodes)){
            return OperationResult.newValidateFailOperationResult("终端唯一编码不能为空");
        }
        if(deviceUpgradeId==null){
            return OperationResult.newValidateFailOperationResult("apk ID不能为空");
        }
        DeviceUpgrade deviceUpgrade = deviceUpgradeMapper.getApkById(deviceUpgradeId);
        if(deviceUpgrade==null){
            return OperationResult.newValidateFailOperationResult("升级信息不存在，请检查参数是否正确");
        }
        List<String> codes = null;
        Long serialNo = System.currentTimeMillis();
        //日志信息
        String msg = "";
        if ( StringUtils.isNotBlank(deviceCodes) ) {
            DeviceSetting setting = new DeviceSetting();
            setting.setUpdateTime(serialNo);
            codes = Arrays.asList(deviceCodes.split(","));
            if (BusinessConstant.DEVICE_UPGRADE_TYPE_SOFTWARE == deviceUpgrade.getUpgradeType()) {
                setting.setSoftwareUpgradeId(deviceUpgradeId);
                msg = ModuleConstant.MODULE_SYSTEM + "-" + ModuleConstant.MODULE_SOFTWARE_MNG;
            } else if (BusinessConstant.DEVICE_UPGRADE_TYPE_FIRMWARE == deviceUpgrade.getUpgradeType()){
                setting.setFirmwareUpgradeId(deviceUpgradeId);
                msg = ModuleConstant.MODULE_SYSTEM + "-" + ModuleConstant.MODULE_FIRMWARE_MNG;
            }
            deviceSettingMapper.updateDeviceSetting(setting, codes);
        }
        // 保存升级信息
        Sysconfig sysConfigVO = sysConfigService.getByType(SysConfigNameEnum.DEVICE_UPGRADE_TIMEOUT);
        Long setTimeOut = Long.parseLong(sysConfigVO.getValue());
        //本次的超时时间
        Long timeOut = serialNo + setTimeOut*60*60*1000;
        //保存升级详情（如果该设备之前已经进行了升级操作，但是未成功，则只修改其更新时间，不插入新的数据）
        for(String deviceCode:codes){
            String versionName = deviceUpgrade.getVersionName();
            Integer versionCode = deviceUpgrade.getVersionCode();
            //查询是否存在该设备正在升级
            Integer count = deviceUpgradeMapper.getCountByVersionCodeAndDeviceCode(versionCode,deviceCode);
            if(count>0){
                //修改时间
                deviceUpgradeMapper.updeteTime(versionCode,deviceCode,BusinessConstant.DEVICE_UPGRADE_DOING,serialNo,timeOut);
            }else{
                //添加新数据
                deviceUpgradeMapper.insertDeviceUpgradeInfo(deviceUpgradeId,versionName,versionCode,serialNo,timeOut,deviceCode,BusinessConstant.DEVICE_UPGRADE_DOING);
            }
        }
        // 保存操作日志
        saveLog( ip, "设置终端升级信息，升级为：[" + deviceUpgrade.getUpgradeName() + "]",msg);
        // 刷新缓存,不影响事务操作
        try {
            DeviceSettingType settingType = (BusinessConstant.DEVICE_UPGRADE_TYPE_SOFTWARE == deviceUpgrade.getUpgradeType() ? DeviceSettingType.SOFTWARE_UPGRADE : DeviceSettingType.FIRMWARE_UPGRADE);
            deviceService.flushDeviceStateCache(settingType, codes, serialNo);
            return OperationResult.newSuccessTipsOperationResult("设置终端升级信息成功");
        } catch (Exception e) {
            String error = "设置终端升级信息，更新缓存异常：" + e.getMessage();
            return OperationResult.newValidateFailOperationResult(error);
        }
    }

    @Override
    public OperationResult<Object> deviceUpgradeInfo(String deviceName, String deviceSerialNum, Long deviceUpgradeId, Integer pageNum, Integer pageSize) {
       if(deviceUpgradeId==null){
           return OperationResult.newValidateFailOperationResult("请传入apk的id");
       }
       Long newTime = System.currentTimeMillis();
        PageHelper.startPage(pageNum, pageSize);
        Page<DeviceUpgradeInfoVO> deviceUpgradeInfoVOS = deviceUpgradeMapper.deviceUpgradeInfo(deviceName,deviceSerialNum,deviceUpgradeId,newTime);
        PageInfo<DeviceUpgradeInfoVO> pageInfo = new PageInfo<>(deviceUpgradeInfoVOS);
        return OperationResult.newSuccessOperationResult(pageInfo);
    }

    @Override
    public OperationResult<Object> getApkUpgradeNumDetail(Long deviceUpgradeId) {
        //升级终端总数
        Integer totalNum = deviceUpgradeMapper.getUpgradeNum(deviceUpgradeId);
        //升级成功的终端数
        Integer successNum = deviceUpgradeMapper.getUpgradeSuccessNum(deviceUpgradeId);
        //升级中的终端数
        Long newTime = System.currentTimeMillis();
        Integer doingNum = deviceUpgradeMapper.getUpgradeDoingNum(deviceUpgradeId,newTime);
        //升级失败的终端数
        Integer failedNum = totalNum-successNum-doingNum;
        Map<String,Integer> resultMap  = new HashMap<>();
        resultMap.put("totalNum",totalNum);
        resultMap.put("successNum",successNum);
        resultMap.put("failedNum",failedNum);
        resultMap.put("doingNum",doingNum);
        return OperationResult.newSuccessOperationResult(resultMap);
    }

    private void saveLog(String operationIp, String keyWords, String module) {
        // 保存操作日志
        OperationLog operationLog = new OperationLog();
        operationLog.setOperationContent(keyWords);
        operationLog.setOperationModule(module);
        operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
        operationLog.setOperationTime(System.currentTimeMillis());
        operationLog.setUserName(UserContextHolder.currentUser().getUserName());
        operationLog.setRealname(UserContextHolder.currentUser().getRealName());
        operationLog.setOperationIp(operationIp);
        operationLogService.saveOperationLog(operationLog);
    }

    private String buildPathName(String contextFileName) {
        return contextFileName.toString().replace("\\", "/");
    }
}
